package com.sloth.bear.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sloth.bear.common.ResultCode;
import com.sloth.bear.dto.entity.Doc;
import com.sloth.bear.dto.request.DocListRequest;
import com.sloth.bear.dto.request.DocumentMoveRequest;
import com.sloth.bear.dto.request.DocumentRequest;
import com.sloth.bear.dto.request.DocumentSortUpdateRequest;
import com.sloth.bear.dto.vo.DocumentDetailsVo;
import com.sloth.bear.dto.vo.DocumentListVo;
import com.sloth.bear.exception.BusinessException;
import com.sloth.bear.mapper.DocumentMapper;
import com.sloth.bear.service.DocItemService;
import com.sloth.bear.service.DocService;
import com.sloth.bear.util.BaseHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 文档服务实现类
 */
@RequiredArgsConstructor
@Service
public class DocServiceImpl implements DocService {

    private final DocumentMapper documentMapper;
    private final DocItemService docItemService;

    @Override
    public List<DocumentListVo> listDoc(DocListRequest request) {
        List<Doc> allDocuments = documentMapper.selectList(Wrappers.<Doc>lambdaQuery()
                .eq(request.getNamespaceId() != null, Doc::getNamespaceId, request.getNamespaceId())
                .eq(request.getIsFavorite() != null, Doc::getIsFavorite, request.getIsFavorite())
                .orderByDesc(Doc::getSortNo)
                .orderByDesc(Doc::getCreatedTime));
        return buildTreeStructure(allDocuments, null);
    }

    @Override
    public DocumentDetailsVo getDocumentById(Long id) {
        Doc document = documentMapper.selectById(id);
        DocumentDetailsVo vo = BaseHelper.r2t(document, DocumentDetailsVo.class);
        // 加载关联的子项
        vo.setItems(docItemService.getItemsByDocumentId(id));
        return vo;
    }

    @Override
    public DocumentListVo createDocument(DocumentRequest request) {
        // 验证父文档是否存在
        if (request.getParentId() != null) {
            Doc parent = documentMapper.selectById(request.getParentId());
            if (parent == null) {
                throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "父文档不存在");
            }
        }

        Doc document = BaseHelper.r2t(request, Doc.class);
        int result = documentMapper.insert(document);
        if (result <= 0) {
            throw new BusinessException(ResultCode.DOCUMENT_CREATE_FAILED);
        }
        return convertToVO(document);
    }

    @Override
    public DocumentListVo updateDocument(Long id, DocumentRequest request) {
        Doc existDocument = documentMapper.selectById(id);
        if (existDocument == null) {
            throw new BusinessException(ResultCode.DOCUMENT_NOT_FOUND);
        }

        // 验证父文档是否存在
        if (request.getParentId() != null && !request.getParentId().equals(existDocument.getParentId())) {
            Doc parent = documentMapper.selectById(request.getParentId());
            if (parent == null) {
                throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "父文档不存在");
            }
        }

        BeanUtils.copyProperties(request, existDocument);
        int result = documentMapper.updateById(existDocument);
        if (result <= 0) {
            throw new BusinessException(ResultCode.DOCUMENT_UPDATE_FAILED);
        }
        return convertToVO(existDocument);
    }

    @Override
    public boolean deleteDocument(Long id) {
        if (id == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "文档ID不能为空");
        }

        Doc existDocument = documentMapper.selectById(id);
        if (existDocument == null) {
            throw new BusinessException(ResultCode.DOCUMENT_NOT_FOUND);
        }

        // 检查是否有子文档，如果有则不能删除
        long childCount = documentMapper.selectCount(Wrappers.<Doc>lambdaQuery()
                .eq(Doc::getParentId, id));
        if (childCount > 0) {
            throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "文档存在子文档，不能删除");
        }

        int result = documentMapper.deleteById(id);
        if (result <= 0) {
            throw new BusinessException(ResultCode.DOCUMENT_DELETE_FAILED);
        }
        return true;
    }

    // 私有方法

    private DocumentListVo convertToVO(Doc document) {
        DocumentListVo vo = new DocumentListVo();
        vo.setId(document.getId());
        vo.setName(document.getName());
        vo.setNamespaceId(document.getNamespaceId());
        vo.setSortNo(document.getSortNo());
        vo.setChildren(new ArrayList<>());
        return vo;
    }

    private List<DocumentListVo> buildTreeStructure(List<Doc> allDocuments, Long parentId) {
        List<DocumentListVo> result = new ArrayList<>();

        // 先过滤出符合条件的文档并按sortNo排序
        allDocuments.stream()
                .filter(document -> (parentId == null && document.getParentId() == null) ||
                        (parentId != null && parentId.equals(document.getParentId())))
                .sorted(Comparator.comparing(document -> document.getSortNo() != null ? document.getSortNo() : 0))
                .forEach(document -> {
                    DocumentListVo vo = convertToVO(document);
                    List<DocumentListVo> children = buildTreeStructure(allDocuments, document.getId());
                    vo.setChildren(children);
                    result.add(vo);
                });

        return result;
    }

    @Override
    @Transactional
    public boolean moveDocument(Long documentId, DocumentMoveRequest request) {
        if (documentId == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "文档ID不能为空");
        }

        // 检查源文档是否存在
        Doc sourceDocument = documentMapper.selectById(documentId);
        if (sourceDocument == null) {
            throw new BusinessException(ResultCode.DOCUMENT_NOT_FOUND);
        }

        // 检查目标父文档是否存在（如果不为null）
        if (request.getParentId() != null) {
            Doc targetParent = documentMapper.selectById(request.getParentId());
            if (targetParent == null) {
                throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "目标父文档不存在");
            }

            // 验证是否会造成循环引用
            if (!validateMove(documentId, request.getParentId())) {
                throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "移动操作会造成循环引用");
            }
        }

        // 更新文档的父文档和排序号
        sourceDocument.setParentId(request.getParentId());
        sourceDocument.setSortNo(request.getSortNo());

        int result = documentMapper.updateById(sourceDocument);
        if (result <= 0) {
            throw new BusinessException(ResultCode.DOCUMENT_UPDATE_FAILED);
        }

        return true;
    }

    @Override
    @Transactional
    public boolean batchUpdateSort(DocumentSortUpdateRequest request) {
        if (request.getUpdates() == null || request.getUpdates().isEmpty()) {
            throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "更新列表不能为空");
        }

        for (DocumentSortUpdateRequest.SortUpdate update : request.getUpdates()) {
            Doc document = documentMapper.selectById(update.getId());
            if (document == null) {
                throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "文档不存在: " + update.getId());
            }

            document.setSortNo(update.getSortNo());
            int result = documentMapper.updateById(document);
            if (result <= 0) {
                throw new BusinessException(ResultCode.DOCUMENT_UPDATE_FAILED);
            }
        }

        return true;
    }

    @Override
    public boolean validateMove(Long sourceId, Long targetId) {
        if (sourceId == null || targetId == null) {
            return true; // 移动到根级别总是安全的
        }

        if (sourceId.equals(targetId)) {
            return false; // 不能移动到自己身上
        }

        // 检查目标文档是否是源文档的后代
        return !isDescendant(sourceId, targetId);
    }

    /**
     * 检查目标文档是否是源文档的后代
     */
    private boolean isDescendant(Long ancestorId, Long nodeId) {
        if (ancestorId == null || nodeId == null) {
            return false;
        }

        if (ancestorId.equals(nodeId)) {
            return true;
        }

        // 使用广度优先搜索避免深度递归
        Set<Long> visited = new HashSet<>();
        List<Long> currentLevel = new ArrayList<>();
        currentLevel.add(nodeId);

        while (!currentLevel.isEmpty()) {
            List<Long> nextLevel = new ArrayList<>();

            for (Long currentId : currentLevel) {
                if (visited.contains(currentId)) {
                    continue; // 避免循环
                }
                visited.add(currentId);

                Doc document = documentMapper.selectById(currentId);
                if (document != null && document.getParentId() != null) {
                    if (ancestorId.equals(document.getParentId())) {
                        return true; // 找到了祖先关系
                    }
                    nextLevel.add(document.getParentId());
                }
            }

            currentLevel = nextLevel;
        }

        return false;
    }

}